#include "appupdater.h"

#include <QCoreApplication>
#include <QDebug>
#include <QDir>
#include <QFile>
#include <QProcess>
#include <QStandardPaths>

#include "IniConfig.h"

const QString AppUpdater::DEFAULT_UPDATE_URL = "http://yang.cyou:8080/update/";

AppUpdater::AppUpdater(const QString& appId, const QString& currentVersion, QObject* parent)
    : QObject(parent),
      m_appId(appId),
      m_currentVersion(currentVersion),
      m_downloadReply(nullptr),
      m_downloadedFile(nullptr)
{
    m_networkManager = new QNetworkAccessManager(this);
    loadOrInitializeUpdateUrl();
}

AppUpdater::~AppUpdater()
{
    if (m_downloadReply) {
        if (m_downloadReply->isRunning()) {
            m_downloadReply->abort();
        }
        m_downloadReply->deleteLater();
    }
    if (m_downloadedFile) {
        if (m_downloadedFile->isOpen()) {
            m_downloadedFile->close();
        }
        delete m_downloadedFile;
        m_downloadedFile = nullptr;
    }
}

void AppUpdater::loadOrInitializeUpdateUrl()
{
    using namespace IniConfigGlobal;

    // 检查是否已有更新URL配置
    if (!hasKey("Server/UpdateUrl")) {
        // 首次运行，设置默认更新URL
        setValue("Server/UpdateUrl", DEFAULT_UPDATE_URL);
        qDebug() << "AppUpdater: Created default update URL configuration";
    }

    // 读取更新URL
    m_updateCheckUrlBase = getString("Server/UpdateUrl", DEFAULT_UPDATE_URL);

    // 确保URL以斜杠结尾
    if (!m_updateCheckUrlBase.endsWith('/')) {
        m_updateCheckUrlBase += '/';
    }

    qDebug() << "AppUpdater: Loaded update URL:" << m_updateCheckUrlBase;
}

void AppUpdater::checkForUpdates()
{
    if (m_appId.isEmpty() || m_currentVersion.isEmpty() || m_updateCheckUrlBase.isEmpty()) {
        qWarning() << "AppID, CurrentVersion, or UpdateCheckUrlBase (" << m_updateCheckUrlBase
                   << ") is not set correctly.";
        emit errorOccurred("更新服务配置不完整。");
        return;
    }
    if (m_downloadReply && m_downloadReply->isRunning()) {
        qWarning() << "Download in progress, please wait for it to finish before "
                      "checking for updates.";
        emit errorOccurred("下载正在进行中，请稍后再试。");
        return;
    }

    QUrl url(m_updateCheckUrlBase + m_appId + "/?version=" + m_currentVersion);
    qDebug() << "Checking for updates at" << url.toString();
    emit updateStatusMessage(QString("正在检查更新 (%1)...").arg(m_appId));

    QNetworkRequest request(url);
    request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);

    QNetworkReply* reply = m_networkManager->get(request);
    connect(reply, &QNetworkReply::finished, this,
            [this, reply]() { this->onUpdateCheckReplyFinished(reply); });
}

void AppUpdater::onUpdateCheckReplyFinished(QNetworkReply* reply)
{
    QString currentUrl = reply->url().toString();
    if (reply->error() == QNetworkReply::NoError) {
        QByteArray responseData = reply->readAll();
        qDebug() << "Raw response from" << currentUrl << ":" << responseData;
        QJsonParseError parseError;
        QJsonDocument jsonDoc = QJsonDocument::fromJson(responseData, &parseError);
        if (parseError.error == QJsonParseError::NoError && jsonDoc.isObject()) {
            QJsonObject jsonObj = jsonDoc.object();
            bool updateAvailable = jsonObj.value("update_available").toBool(false);
            QString latestVersion = jsonObj.value("latest_version").toString();
            QString downloadUrl = jsonObj.value("download_url").toString();
            QString releaseNotes = jsonObj.value("release_notes").toString();
            emit updateStatusMessage(
                updateAvailable
                    ? QString("发现新版本: %1").arg(latestVersion)
                    : QString("当前已是最新版本 (%1)")
                          .arg(latestVersion.isEmpty() ? m_currentVersion : latestVersion));
            emit updateCheckFinished(updateAvailable, latestVersion, downloadUrl, releaseNotes);
        } else {
            qWarning() << "JSON parsing error from" << currentUrl << "-" << parseError.errorString()
                       << ". Response:" << responseData;
            emit updateStatusMessage("更新检查失败 (响应格式错误)");
            emit errorOccurred(
                QString("无法解析服务器响应 (JSON错误: %1)").arg(parseError.errorString()));
        }
    } else {
        QString errorMsg = reply->errorString();
        qWarning() << "Network error from" << currentUrl << "-" << reply->error() << ":"
                   << errorMsg;
        emit updateStatusMessage(QString("网络连接失败"));
        emit errorOccurred(QString("网络错误: %1").arg(errorMsg));
    }
    reply->deleteLater();
}

void AppUpdater::startDownload(const QString& downloadUrlStr)
{
    if (m_downloadReply && m_downloadReply->isRunning()) {
        qWarning() << "Another download is already in progress.";
        emit errorOccurred("另一个下载正在进行中。");
        return;
    }

    QUrl downloadUrl(downloadUrlStr);
    if (!downloadUrl.isValid() || downloadUrl.isEmpty()) {
        qWarning() << "Invalid download URL provided:" << downloadUrlStr;
        emit errorOccurred("无效的下载链接。");
        return;
    }

    if (m_downloadedFile) {
        if (m_downloadedFile->isOpen()) m_downloadedFile->close();
        delete m_downloadedFile;
        m_downloadedFile = nullptr;
    }
    if (m_downloadReply) {
        m_downloadReply->deleteLater();
        m_downloadReply = nullptr;
    }

    QString fileName = QFileInfo(downloadUrl.path()).fileName();
    if (fileName.isEmpty()) {
        fileName = m_appId + "_update_package.zip";
    }
    m_targetFilePath = QDir::tempPath() + QDir::separator() + fileName;

    m_downloadedFile = new QFile(m_targetFilePath);
    if (!m_downloadedFile->open(QIODevice::WriteOnly)) {
        qWarning() << "Could not open file for writing:" << m_targetFilePath
                   << m_downloadedFile->errorString();
        emit errorOccurred(QString("无法创建临时文件: %1").arg(m_downloadedFile->errorString()));
        delete m_downloadedFile;
        m_downloadedFile = nullptr;
        m_targetFilePath.clear();
        return;
    }

    qDebug() << "Starting download from" << downloadUrl.toString() << "to" << m_targetFilePath;
    emit updateStatusMessage(QString("开始下载 %1...").arg(fileName));
    emit downloadStarted(fileName);

    QNetworkRequest request(downloadUrl);
    request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);

    m_downloadReply = m_networkManager->get(request);

    connect(m_downloadReply, &QNetworkReply::readyRead, this, &AppUpdater::onDownloadReadyRead);
    connect(m_downloadReply, &QNetworkReply::downloadProgress, this,
            &AppUpdater::onDownloadProgressSlot);
    connect(m_downloadReply, &QNetworkReply::finished, this, &AppUpdater::onDownloadFinishedSlot);
}

void AppUpdater::onDownloadReadyRead()
{
    if (m_downloadReply && m_downloadedFile && m_downloadedFile->isOpen()) {
        m_downloadedFile->write(m_downloadReply->readAll());
    }
}

void AppUpdater::onDownloadProgressSlot(qint64 bytesReceived, qint64 bytesTotal)
{
    emit downloadProgress(bytesReceived, bytesTotal);
    if (bytesTotal > 0) {
        emit updateStatusMessage(QString("下载中... %1MB / %2MB")
                                     .arg(bytesReceived / (1024.0 * 1024.0), 0, 'f', 2)
                                     .arg(bytesTotal / (1024.0 * 1024.0), 0, 'f', 2));
    } else {
        emit updateStatusMessage(
            QString("下载中... %1MB / 未知大小").arg(bytesReceived / (1024.0 * 1024.0), 0, 'f', 2));
    }
}

void AppUpdater::onDownloadFinishedSlot()
{
    if (!m_downloadReply) {
        qWarning() << "onDownloadFinishedSlot called with no active download reply.";
        return;
    }

    QString finalUrl = m_downloadReply->url().toString();
    bool success = false;
    QString errorString;

    if (m_downloadReply->error() == QNetworkReply::NoError) {
        if (m_downloadedFile && m_downloadedFile->isOpen()) {
            m_downloadedFile->flush();
            m_downloadedFile->close();
            success = true;
            qInfo() << "Download successful for" << finalUrl << "saved to" << m_targetFilePath;
            emit updateStatusMessage(
                QString("下载完成: %1").arg(QFileInfo(m_targetFilePath).fileName()));
        } else {
            errorString = "File handle became invalid during download.";
            qWarning() << "Download finished but file handle was invalid for" << finalUrl;
            emit updateStatusMessage("下载失败 (文件错误)");
        }
    } else {
        errorString = m_downloadReply->errorString();
        if (m_downloadReply->error() == QNetworkReply::OperationCanceledError) {
            qInfo() << "Download cancelled by user for" << finalUrl;
            errorString = "用户取消了下载";
            emit updateStatusMessage("下载已取消");
        } else {
            qWarning() << "Download error for" << finalUrl << "-" << m_downloadReply->error() << ":"
                       << errorString;
            emit updateStatusMessage(QString("下载失败"));
        }
        if (m_downloadedFile) {
            if (m_downloadedFile->isOpen()) m_downloadedFile->close();
            m_downloadedFile->remove();
        }
    }

    emit downloadFinished(success ? m_targetFilePath : QString(), success, errorString);

    m_downloadReply->deleteLater();
    m_downloadReply = nullptr;

    if (m_downloadedFile) {
        delete m_downloadedFile;
        m_downloadedFile = nullptr;
    }
    m_targetFilePath.clear();
}

void AppUpdater::cancelDownload()
{
    if (m_downloadReply && m_downloadReply->isRunning()) {
        qDebug() << "User requested to cancel download.";
        emit updateStatusMessage("正在取消下载...");
        m_downloadReply->abort();  // This will trigger onDownloadFinishedSlot
        // onDownloadFinishedSlot will handle file cleanup and emitting appropriate signals
    } else {
        qDebug() << "No active download to cancel.";
    }
}

void AppUpdater::installUpdate()
{
    if (m_targetFilePath.isEmpty() || !QFile::exists(m_targetFilePath)) {
        qWarning() << "AppUpdater::installUpdate: No valid downloaded file path available ("
                   << m_targetFilePath << ") or file does not exist.";
        emit errorOccurred("下载的更新文件无效或不存在。请重新下载。");
        return;
    }

    QString updaterProgramName;
#if defined(Q_OS_WIN)
    updaterProgramName = "updater.exe";
#elif defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
    updaterProgramName = "updater";  // Ensure this matches your compiled updater name
#else
    // Fallback for other OS, or could emit an error
    qWarning() << "AppUpdater::installUpdate: Updater program name not defined for this OS.";
    updaterProgramName = "updater";
#endif

    QString updaterFullPath =
        QCoreApplication::applicationDirPath() + QDir::separator() + updaterProgramName;

    if (!QFile::exists(updaterFullPath)) {
        qWarning() << "AppUpdater::installUpdate: Updater program not found at" << updaterFullPath;
        emit errorOccurred(
            QString("更新核心程序 (%1) 未找到。无法继续更新。").arg(updaterProgramName));
        return;
    }

    QString currentAppPath = QCoreApplication::applicationFilePath();
    qint64 currentAppPid = QCoreApplication::applicationPid();

    QStringList arguments;
    arguments << m_targetFilePath;                // Arg 1: path to new executable
    arguments << currentAppPath;                  // Arg 2: path to old (current) executable
    arguments << QString::number(currentAppPid);  // Arg 3: PID of current app

    qInfo() << "AppUpdater::installUpdate: Attempting to launch updater:" << updaterFullPath;
    qInfo() << "AppUpdater::installUpdate: With arguments:" << arguments;

    if (QProcess::startDetached(updaterFullPath, arguments)) {
        qInfo() << "AppUpdater::installUpdate: Updater process launched successfully.";
        emit updateStatusMessage("更新程序已启动，应用程序即将退出...");
        emit readyToQuitForUpdate();  // Signal that the main app can now quit
    } else {
        qWarning() << "AppUpdater::installUpdate: Failed to launch updater process.";
        emit errorOccurred("无法启动更新核心程序。请重试或联系技术支持。");
    }
}
